<script setup lang="ts">
import {
  reactive,
  ref,
  onMounted,
  onBeforeMount,
  computed,
  watch,
  watchEffect
} from "vue";
import { FormInfo, InfoContainer } from "../components";
import {
  chartInfo,
  formInfo,
  tableProps,
  barProps,
  chartResults
} from "../components/interface";
import DeployChart from "./components/DeployChart.vue"
import { TheStackedLineChart, TheLineChart } from "../components/Chart";
import { AppTable } from "../components";
import { columns } from "./components/columns";
import { Log } from "./components";
import ProgressBar from "./components/ProgressBar.vue";
import axios from "axios";
import { fa } from "element-plus/es/locale/index.mjs";
import { bitUrlApi } from "../../../api/utils";
import ECT_MOCK from "./assets/data_continueTraining_mock.json"
import 'echarts/lib/component/markLine'


defineOptions({
  name: "AppRoutine"
});

const fetchData = async light_model_apply => {
  try {
    const res = await axios.post(bitUrlApi("/deploy/light_model_list"), {
      model_class: "knowledge",
      model_apply: light_model_apply,
      is_light: false
    });
    console.log("可以选择的轻量化模型", res);

    let source_models = res.data.data.models;
    console.log(source_models);

    // 清空 models_table.value
    formProps1.formInfoList[1].options = [];

    for (let i = 0; i < source_models.length; i++) {
      formProps1.formInfoList[1].options.push({
        label: source_models[i],
        value: source_models[i]
      });
    }
  } catch (error) {
    console.error("获取数据时出错:", error);
  }
};

// 使用reactive实现数据自动绑定到组件上
const formProps1: formInfo = reactive({
  title: "量化设置",
  btnNames: ["创建实例", undefined, undefined],
  btnDisabled: [false, false, false],
  formInfoList: [
    {
      id: 1,
      title: "应用领域",
      inputType: "0",
      placeholder: "请选择应用领域",
      options: [
        {
          value: "outlier_detection",
          label: "工业异常检测"
        },
        {
          value: "fault_diagnosis",
          label: "工业故障诊断"
        }
      ]
    },
    {
      id: 2,
      title: "模型名称",
      inputType: "0",
      placeholder: "请选择模型名称",
      options: undefined
    },
    {
      id: 3,
      title: "算法选择",
      inputType: "0",
      placeholder: "请选择算法",
      options: [
        { label: "动态压缩", value: "fedlamp" },
        { label: "均值融合", value: "fedavg" },
        { label: "稀疏压缩", value: "qsparse" }
      ]
    }
  ]
});

const formInfo1 = ref();

watchEffect(() => {
  if (!formInfo1.value) {
    return;
  }
  if (formInfo1.value.infoChildren[0].value != undefined) {
    fetchData(formInfo1.value.infoChildren[0].value);
    formInfo1.value.infoChildren[1].value = undefined;
    formInfo1.value.infoChildren[2].value = undefined;
  }
});

function clickBtn() {
  if (!formInfo1.value.infoChildren[0].value) {
    formInfo1.value.infoChildren[0].value = "工业异常检测";
  }
  if (!formInfo1.value.infoChildren[1].value) {
    alert("请选择模型名称！");
    return;
  }
  if (!formInfo1.value.infoChildren[2].value) {
    alert("请选择算法！");
    return;
  }
  startLight();
}

async function startLight() {
  if (lighting.value) {
    alert("模型正在量化中，请稍后！");
    return;
  }
  console.log("model apply: ", formInfo1.value.infoChildren[0].value);
  console.log("model name: ", formInfo1.value.infoChildren[1].value);
  console.log("light method: ", formInfo1.value.infoChildren[2].value);
  try {
    const res = await axios.post(bitUrlApi("/deploy/light_create"), {
      model_apply: formInfo1.value.infoChildren[0].value,
      source_model: formInfo1.value.infoChildren[1].value,
      is_light: true,
      light_method: formInfo1.value.infoChildren[2].value
    });
    // let res = null
    console.log(res);
    lighting.value = true;
    formProps1.btnNames[0] = "量化中······";
    formProps1.btnDisabled[0] = true;
    finish.value = false;
    increasePercentage();
  } catch (error) {
    console.error("请求量化出错:", error);
    alert(`请求量化出错: ${error}`);
  }
  console.log("与后端通信，创建实例！");
}

onMounted(() => {
  formInfo1.value.infoChildren[0].inputValue = "工业异常检测";
});

watchEffect(() => {
  if (!formInfo1.value) {
    return;
  }
  if (formInfo1.value.infoChildren[0].value != undefined) {
    // formInfo1.value.infoChildren[3].value = undefined
    // formProps1.formInfoList[3].options = algorithm_dict.value[formInfo1.value.infoChildren[2].value]
    // formInfo1.value.infoChildren[4].value = undefined
    // formProps1.formInfoList[4].options = dataset_dict.value[formInfo1.value.infoChildren[2].value]
    // console.log(`"${formInfo1.value.infoChildren[1].value}"`)
    // console.log(deploy_domain_option_dict[`"${formInfo1.value.infoChildren[1].value}"`])
  }
  //  if (formInfo1.value && formInfo1.value.infoChildren[1].value) {
  //   console.log(formInfo1.value.infoChildren[1].value);
  //  }
});

const formProps2: formInfo = reactive({
  title: "部署设置",
  btnNames: ["开始部署", undefined, undefined],
  btnDisabled: [false, false, false],
  formInfoList: [
    {
      id: 1,
      title: "模型名称",
      inputType: "0",
      placeholder: "请选择模型",
      options: undefined
    },
    {
      id: 2,
      title: "边缘网关",
      inputType: "2",
      placeholder: "请输入网关",
      options: undefined
    },
    {
      id: 3,
      title: "IP地址",
      inputType: "2",
      placeholder: "请输入IP地址",
      options: undefined
    },
    {
      id: 4,
      title: "端口号",
      inputType: "2",
      placeholder: "请输入端口号",
      options: undefined
    },
    {
      id: 5,
      title: "镜像",
      inputType: "0",
      placeholder: "请选择镜像",
      options: [
        {
          label: "Ubuntu16.04_Pyotch1.0.0_Python3.6",
          value: "Ubuntu16.04_Pyotch1.0.0_Python3.6"
        },
        {
          label: "Ubuntu18.04_Pyotch1.0.0_Python3.7",
          value: "Ubuntu18.04_Pyotch1.0.0_Python3.7"
        },
        {
          label: "Ubuntu20.04_Pyotch1.7.0_Python3.9",
          value: "Ubuntu20.04_Pyotch1.7.0_Python3.9"
        },
        {
          label: "Ubuntu20.04_Pyotch1.11.0_Python3.9",
          value: "Ubuntu20.04_Pyotch1.11.0_Python3.9"
        }
      ]
    }
  ]
});

const fetchDeployList = async () => {
  try {
    const res = await axios.post(bitUrlApi("/manage/model_table"), {
      model_class: "knowledge"
    });
    let source_models = res.data.data.models;
    console.log("所有的模型：", source_models);

    // 清空 models_table.value
    formProps2.formInfoList[0].options = [];

    for (let i = 0; i < source_models.length; i++) {
      formProps2.formInfoList[0].options.push({
        label: source_models[i].model_name,
        value: source_models[i].model_name
      });
    }
  } catch (error) {
    console.error("获取数据时出错:", error);
  }
};

onMounted(() => {
  fetchDeployList();
});

const formInfo2 = ref();
const logDatas1 = reactive({
  logNames: [
    "模型名称",
    "应用领域",
    "压缩前大小",
    "压缩后大小",
    "压缩前性能",
    "压缩后性能",
    "压缩概要"
  ],
  array: []
});
const logDatas2 = reactive({
  logNames: ["边缘网关", "地址", "模型名称", "镜像"],
  array: []
});

const barProps1: barProps = reactive({
  title: "量化进度",
  fetchData: undefined
});

const textareaValue = ref();
const barRef = ref();

const lighting = ref(false);

const increasePercentage = () => {
  barRef.value.progress = 0;
  // show_progress.value = true;
  // button_disabled.value = true;

  const minTotalTime = 1000 * 10;
  const maxTotalTime = 1000 * 20;
  const intervalTime = 0.1; // 间隔时间：1秒

  const totalTime =
    minTotalTime + Math.random() * (maxTotalTime - minTotalTime); // 随机总时间

  const startTime = Date.now(); // 开始时间

  const interval = setInterval(() => {
    const currentTime = Date.now(); // 当前时间
    const elapsedTime = currentTime - startTime; // 已经过的时间
    let progress = Math.min((elapsedTime / totalTime) * 100, 100); // 当前进度

    if (!finish.value && progress > 96) {
      progress = 96;
    }

    barRef.value.progress = Math.floor(progress); // 设置进度

    if (progress >= 100) {
      // showChart.value = true;
      clearInterval(interval);
      // button_disabled.value = false;
      // button_text.value = "开始任务";
    }
  }, intervalTime);
};

const finish = ref(false);

const table_data_get = async () => {
  try {
    const res = await axios.post(bitUrlApi("/deploy/light_table_state"));
    console.log("light_table: ", res);
    let tabel_content = res.data.data;
    console.log("tabel_content", tabel_content);
    if (tabel_content.model_apply == "outlier_detection") {
      tabel_content.model_apply = "异常检测";
    } else if (tabel_content.model_apply == "fault_diagnosis") {
      tabel_content.model_apply = "故障诊断";
    }

    // if (tabel_content.value.model_size == undefined)
    if (tabel_content.is_train) {
      console.log("task has not finished!");
      finish.value = false;
      return;
    }

    finish.value = true;

    if (barRef.value.progress != 100) {
      return;
    }

    let model_name = tabel_content.model_name;
    let model_apply = tabel_content.model_apply;
    let old_size = parseFloat(
      tabel_content.origin_model_size.replace("MB", "")
    );
    let new_size = parseFloat(tabel_content.model_size.replace("MB", ""));
    let old_perform = parseFloat(
      tabel_content.origin_model_perform.replace("%", "")
    );
    let new_perform = parseFloat(tabel_content.model_perform.replace("%", ""));
    const compressionRatio = Math.round((new_size / old_size) * 100) / 100;
    const performRation = Math.round((new_perform / old_perform) * 100) / 100;

    let timeRegex = /^[0-9]{4}-[0-9]{2}-[0-9]{2}_[0-9]{2}:[0-9]{2}:[0-9]{2}/;
    let match = model_name.match(timeRegex);
    let time_step = match ? match[0] : getCurrentTime();

    logDatas1.array.push({
      timeStamp: time_step,
      datas: {
        data1: model_name,
        data2: model_apply,
        data3: `${old_size}MB`,
        data4: `${new_size}MB`,
        data5: `${old_perform}%`,
        data6: `${new_perform}%`,
        data7: `压缩后的模型大小是原始模型大小的 ${compressionRatio} 倍，性能为 ${performRation} 倍`
      }
    });

    formProps1.btnNames[0] = "开始量化";
    formProps1.btnDisabled[0] = false;

    lighting.value = false;
  } catch (error) {
    console.error("获取数据时出错:", error);
  }
};

function getCurrentTime() {
  const now = new Date();

  const year = now.getFullYear();
  const month = String(now.getMonth() + 1).padStart(2, "0"); // 月份从0开始，需要+1
  const day = String(now.getDate()).padStart(2, "0");

  const hours = String(now.getHours()).padStart(2, "0");
  const minutes = String(now.getMinutes()).padStart(2, "0");
  const seconds = String(now.getSeconds()).padStart(2, "0");

  // 返回格式化后的时间字符串
  return `${year}-${month}-${day}_${hours}:${minutes}:${seconds}`;
}

watch(
  () => lighting.value,
  (newVal, oldVal) => {
    console.log(lighting);
    if (newVal) {
      console.log("模型开始训练");
      startTimer();
    } else if (!newVal) {
      stopTimer();
    }
  }
);

const timer = ref(null);

function startTimer() {
  // 当 fetchData 传入数据时，启动定时器，每秒调用一次 handleTimer 方法
  if (timer.value === null) {
    timer.value = setInterval(handleTimer, 3000);
  }
}

function stopTimer() {
  // 停止定时器
  if (timer.value !== null) {
    clearInterval(timer.value);
    timer.value = null;
  }
}

function handleTimer() {
  console.log("handleTimer");
  table_data_get();
}

const startDeploy = () => {
  if (
    !formInfo2.value.infoChildren[0].value ||
    !formInfo2.value.infoChildren[1].inputValue ||
    !formInfo2.value.infoChildren[2].inputValue ||
    !formInfo2.value.infoChildren[3].inputValue ||
    !formInfo2.value.infoChildren[4].value
  ) {
    alert("请填写所有内容！");
    return;
  }
  let time_step = getCurrentTime();
  let model_name = formInfo2.value.infoChildren[0].value;
  let network_gate = formInfo2.value.infoChildren[1].inputValue;
  let address = `${formInfo2.value.infoChildren[2].inputValue}:${formInfo2.value.infoChildren[3].inputValue}`;
  let image = formInfo2.value.infoChildren[4].value;

  logDatas2.array.push({
    timeStamp: time_step,
    datas: {
      data1: network_gate,
      data2: address,
      data3: model_name,
      data4: image
    }
  });
};

const showTransferChart = ref(false);
const transferMock = true
const transferInfoProps: formInfo = reactive({
  title: "边侧训练",
  btnNames: ["开始训练", "停止", undefined],
  btnDisabled: [false, false, false],
  btnLoading: [false, false, false],
  formInfoList: [
    {
      id: 1,
      title: "模型选择",
      inputType: "0",
      placeholder: "请选择模型",
      options: [
        {
          value: "0",
          label: "yolox"
        }
      ]
    },
    {
      id: 2,
      title: "数据选择",
      inputType: "1",
      options: undefined,
      placeholder: "请选择数据文件"
    }
  ]
});
const transferChartProps: chartInfo = reactive({
  title: "",
  legend: ["精度"],
  xAxisName: "迭代轮数",
  xAxisData: ["0"],
  yAxisSetting: {
    name: "精度"
  },
  seriesData: [
    {
      name: "精度",
      data: [0.0],
      markLine: {
        silent: true,  // 这个属性决定是否忽略交互，设置为true
        data: [
          { yAxis: 50 }
        ],
        symbol: ['none', 'none']
      }
    }
  ]
});

const renderTransferStaticChart = () => {
  const xData = [], sData = []
  for (let data of ECT_MOCK) {
    xData.push(data['epoch'])
    sData.push(Number(data['accuracy']))
  }
  transferChartProps.xAxisData = xData
  transferChartProps.seriesData[0]['data'] = sData
  transferChartProps.seriesData[0]['markLine']['data'][0]['yAxis'] = "70.003"
  console.log(transferChartProps);
}

const initTransferChartData = () => {
  transferChartProps.xAxisData = []
  transferChartProps.seriesData[0]['data'] = []
}

onMounted(() => {
  renderTransferStaticChart()
})

const sleep = (ms: number) => {
  return new Promise(resolve => setTimeout(resolve, ms));
};
const stopFlag = ref(true)
const transferBtnClick1 = async e => {
  transferInfoProps.btnLoading[0] = true
  transferInfoProps.btnNames[0] = "训练中"
  initTransferChartData()
  if (transferMock) {
    stopFlag.value = false
    for (let data of ECT_MOCK) {
      if (stopFlag.value) break
      await sleep(Number(data['time']) * 1000)
      transferChartProps.xAxisData.push(data['epoch'])
      transferChartProps.seriesData[0]['data'].push(Number((Number(data['accuracy']) + Number(Math.random() * 0.5)).toFixed(3)))
      if (data['epoch'] == '150') {
        transferInfoProps.btnNames[0] = "开始训练"
        transferInfoProps.btnLoading[0] = false
      }
    }
  } else {

  }
};
const transferBtnClick2 = () => {
  if (transferMock) {
    stopFlag.value = true
  }
  transferInfoProps.btnLoading[0] = false
  transferInfoProps.btnNames[0] = "开始训练"
};
</script>
<template>
  <div>
    <el-row class="app-delpoy" :gutter="20">
      <el-col :span="12">
        <FormInfo ref="formInfo1" :title="formProps1.title" :btnNames="formProps1.btnNames"
          :btnDisabled="formProps1.btnDisabled" :formInfoList="formProps1.formInfoList" @btnClick1="clickBtn">
          <template #afc2>
            <el-divider style="margin-top: 10px; margin-bottom: 10px" />
            <el-col :span="24">
              <ProgressBar ref="barRef" :title="barProps1.title" :fetch-data="barProps1.fetchData" />
            </el-col>
            <el-divider style="margin-top: 10px; margin-bottom: 10px" />
            <el-col :span="24">
              <h4>量化日志</h4>
            </el-col>
            <el-col :span="24">
              <el-scrollbar ref="scrollBarRef" height="36vh">
                <div ref="innerBarRef">
                  <Log v-for="(item, index) in logDatas1.array" :key="index" :logNames="logDatas1.logNames"
                    :log="item" />
                </div>
              </el-scrollbar>
            </el-col>
          </template>
        </FormInfo>
      </el-col>
      <el-col :span="12">
        <FormInfo ref="formInfo2" :title="formProps2.title" :btnNames="formProps2.btnNames"
          :btnDisabled="formProps2.btnDisabled" :formInfoList="formProps2.formInfoList" @btnClick1="startDeploy">
          <template #afc2>
            <!-- 模型选择与新布匹数据 -->
            <el-switch v-model="showTransferChart" class="deploy-transfer-switch" active-text="开启边侧训练" />
            <el-divider style="margin-top: 10px; margin-bottom: 10px" />
            <el-col :span="24">
              <h4>部署日志</h4>
            </el-col>
            <el-col :span="24">
              <el-scrollbar ref="scrollBarRef" height="27vh">
                <div ref="innerBarRef">
                  <Log v-for="(item, index) in logDatas2.array" :key="index" :logNames="logDatas2.logNames"
                    :log="item" />
                </div>
              </el-scrollbar>
            </el-col>
          </template>
        </FormInfo>
      </el-col>
    </el-row>
    <el-row v-if="showTransferChart" :gutter="20">
      <el-col :span="12" style="min-height: 200px">
        <FormInfo class="footer-deploy-transfer" :title="transferInfoProps.title" :btnNames="transferInfoProps.btnNames"
          :btnDisabled="transferInfoProps.btnDisabled" :btnLoading="transferInfoProps.btnLoading"
          :formInfoList="transferInfoProps.formInfoList" @btnClick1="transferBtnClick1"
          @btnClick2="transferBtnClick2" />
      </el-col>
      <el-col :span="12" style="min-height: 200px">
        <InfoContainer class="footer-deploy-transfer">
          <DeployChart :class="['the-stacked-line-chart', 'normal-height']" :title="transferChartProps.title"
            :legend="transferChartProps.legend" :xAxisName="transferChartProps.xAxisName"
            :xAxisData="transferChartProps.xAxisData" :yAxisSetting="transferChartProps.yAxisSetting"
            :seriesData="transferChartProps.seriesData" />
        </InfoContainer>
      </el-col>
    </el-row>
  </div>
</template>

<style lang="scss" scoped>
$input-height: 70px;
$input-title-height: 22px;
$input-row-height: $input-height - $input-title-height;
$input-upload-aside-width: 5%;
$input-upload-container-height: 32px;

.app-delpoy {
  height: 93.5vh;

  .afc1-title {
    font-weight: bold;
  }

  .afc1-content {
    display: flex;
    flex-wrap: wrap;
    justify-content: space-between;

    .afc1-item {
      flex: 0 0 48%;

      span {
        color: rgb(176 177 179);
      }
    }
  }
}

.the-stacked-line-chart {
  overflow: hidden;
  // width: 100px;
}

.normal-height {
  height: 35vh;
}

.input-title {
  height: $input-title-height;
  margin-bottom: 1vh;
  font-size: 14px;
  font-weight: 400;
  line-height: $input-title-height;
}

.input-info-row {
  height: $input-row-height;
}

.input-upload-container {
  .input-upload-aside {
    width: $input-upload-aside-width;
    overflow: hidden;

    .input-upload-btn {
      width: 100% !important;
      height: $input-upload-container-height;
      line-height: $input-upload-container-height;
      cursor: pointer;
      border-top: 1px solid rgb(220 223 230);
      border-right: 1px solid rgb(220 223 230);
      border-bottom: 1px solid rgb(220 223 230);
      border-top-right-radius: 4px;
      border-bottom-right-radius: 4px;
    }

    .input-upload-btn:hover {
      background-color: rgb(234 234 234);
    }
  }

  .input-upload-main {
    overflow: hidden;
  }
}

.info-btn {
  width: 100% !important;
  margin-top: 2vh;
}

.form_btn1 {
  background-color: #0c78e1;
}

.form_btn2 {
  background-color: #fcfcfc !important;
}

.form_btn3 {
  background-color: #c34d4d;
}

.custom-textarea {
  width: 100%;
  max-width: 600px;
  border: 1px solid #dcdfe6;
  border-radius: 4px;
}

.deploy-transfer-switch {
  margin-top: 2vh;
}

.footer-deploy-transfer {
  height: 90%;
  margin-top: 2vh;
  margin-bottom: 2vh;
  overflow: hidden;
}
</style>
